import database as db
from twisted.python import log
import commands
from update_logic import locking, check_update


# request to perform an action
requests = {}

def req(func):
    requests[func.func_name.upper()] = func
    return func
  
    
########### SYSTEM REQUESTS: ###########    

def ENTER(player, loc_id, (x,y) = (None,None)):
    ''' Places character at designated location or if not specified: any free safe location '''
    
    if not player.creature:
        raise Exception, "No creature for player"+str(player)
    player.loc_id = loc_id
    @locking(loc_id, "system")
    def add(lock):
        with db.Handler(True) as h:
            if x == None or y == None:
                targ_cell = None
            else:
                targ_cell = h.session.query(db.Cell).filter(db.Cell.coords == (x,y))
            player.creature = h.session.merge(player.creature)
            r = db.Request(type = 'enter',
                           source = player.creature,
                           loc_id = loc_id,
                           target_cell = targ_cell,
                           cost = 20)
            h.session.add(r)
        player.committed = True
        check_update(player)
    
def EXIT(player):
    ''' removes creature from location '''
    # TODO:
 

########### REQUESTS: ###########    

@req
def MOVE(player, info):
    ''' Moves character in direction '''
    
    @locking(player.loc_id, "move")
    def move(lock):
        with db.Handler(True) as h:
            cre = player.creature
            h.session.add(cre)
            if not cre.cell:
                player.sendLine(commands.error("You have not yet entered the game"))
                return
            
            if not info:
                player.sendLine(commands.error("No direction given for 'move'"))
                return
            
            if not set(info.lower()) <= set('nswe'):
                player.sendLine(commands.error("unknown direction given: "+info))
                return

            #check if cell is passable is performed when updating logic
            r = db.Request(source = cre,
                           type = 'move',
                           loc_id = player.loc_id,
                           info = info,
                           cost = 20
                           )
            h.session.add(r)


@req
def COMMIT(player):
    if not player.loc_id:
        raise Exception("Player is not yet in any location to commit")
    
    @locking(player.loc_id, "commit", toThread=False)
    def upd(lock):
        player.committed = True
        check_update(player)

@req
def CANCEL(player, n = None):
    ''' cancells n actions '''

@req
def ATTACK(player, target):
    if not player.loc_id:
        player.sendLine(commands.error("player have no loc_id"))
        return
    @locking(player.loc_id,"attack")
    def attack(lock):
        with db.Handler(True) as h:
            cre = player.creature
            h.session.add(cre)
            if not cre.cell:
                player.sendLine(commands.error("You have not yet entered the game"))
                return  
            target_c = cre.location.strid_objects[target]      
            r = db.Request(source = cre,
                           type = 'attack',
                           loc_id = player.loc_id,
                           target = target_c,
                           cost = 15
                           )
            #h.session.add(r)
            